//################################################################################
// MIT License
// Copyright (c) 2024 ZhangYihua
//
// Change Logs:
// Date           Author       Notes
// 2020-10-14     ZhangYihua   first version
//
// Description  : signed data saturation and truncation, then registered
//################################################################################

module s_sat_tru_reg #(     // range [-(2^(IDW-1))/(2^IFW):(2^(IDW-1)-1)/(2^IFW)]
parameter           IDW                     = 9,    // input data width
parameter           IFW                     = 5,    // input fractional width,  IFW>=IDW is legal
parameter           ODW                     = 7,    // output data width
parameter           OFW                     = 4,    // output fractional width, OFW>=ODW is legal
parameter           TRU_MODE                = "CBB_DEFINE"  // default truncation mode follows cbb_define.v 
//parameter           TRU_MODE                = "FLOOR"   // discade fractional bits directly for less area and higher Fmax
//parameter           TRU_MODE                = "ROUND"   // discade or carry according to MSB of fractonal bits for better DC
) ( 
input                                       rst_n,
input                                       clk,
input                                       cke,

input       signed  [IDW-1:0]               id,     // s(IDW, IFW), the MSB is sign
output  reg signed  [ODW-1:0]               od,     // s(ODW, OFW), the MSB is sign
output  reg                                 over
);

//################################################################################
// define local varialbe and localparam
//################################################################################
wire        signed  [ODW-1:0]               od_c;
wire                                        over_c;

//################################################################################
// main
//################################################################################

s_sat_tru #(     // range [-(2^(IDW-1))/(2^IFW):(2^(IDW-1)-1)/(2^IFW)]
        .IDW                            (IDW                            ),	// input data width
        .IFW                            (IFW                            ),	// input fractional width
        .ODW                            (ODW                            ),	// output data width
        .OFW                            (OFW                            ),	// output fractional width
        .TRU_MODE                       (TRU_MODE                       )
) u_s_sat_tru ( 
        .id                             (id                             ),	// s(IDW, IFW), the MSB is sign
        .od                             (od_c                           ),	// s(ODW, OFW), the MSB is sign
        .over                           (over_c                         )
);

always@(posedge clk or negedge rst_n) begin
    if (rst_n==1'b0) begin
        od <=`U_DLY {ODW{1'b0}};
    end else if (cke==1'b1) begin
        od <=`U_DLY od_c;
    end else
        ;
end

always@(posedge clk or negedge rst_n) begin
    if (rst_n==1'b0) begin
        over <=`U_DLY 1'b0;
    end else begin
        over <=`U_DLY over_c & cke;
    end
end

//################################################################################
// ASSERTION
//################################################################################

`ifdef CBB_ASSERT_ON
// synopsys translate_off

// synopsys translate_on
`endif

endmodule
